package dxn.nl.export.deal.upload;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.util.ListUtils;
import com.alibaba.excel.util.StringUtils;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import dxn.nl.export.deal.netty.SocketManager;
import dxn.nl.file.biz.ImportStatusEnum;
import dxn.nl.file.biz.po.FileImportFileDetail;
import dxn.nl.file.biz.service.ImportFileBaseService;
import dxn.nl.file.client.model.dto.CsExportExcelHeadDto;
import dxn.nl.file.client.model.dto.TransferMessageConfig;
import dxn.nl.file.client.model.dto.TransferMessageData;
import dxn.nl.file.client.model.dto.TransferMessageDto;
import dxn.nl.file.client.model.enums.ExportDealResultTypeEnum;
import dxn.nl.file.client.model.enums.ExportFileTypeEnum;
import dxn.nl.file.client.model.enums.ExportMessageTypeEnum;
import lombok.extern.slf4j.Slf4j;

import java.util.*;

@Slf4j
public class NoModelDataListener extends AnalysisEventListener<Map<Integer, String>> {
    private final String appId;
    private final String sessionId;
    private final String modeCode;
    private Map<Integer, String> headKeyMap = new HashMap<>();
    private final List<CsExportExcelHeadDto> headDtos;

    public String failMessage = null;
    public int lastDealRow=0;
    private final ImportFileBaseService importFileBaseService;
    private final FileImportFileDetail fileDetail;
    /**
     * 每隔5条存储数据库，实际使用中可以100条，然后清理list ，方便内存回收
     */
    private static final int BATCH_COUNT = 200;
    private List<JSONObject> cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);

    public NoModelDataListener(FileImportFileDetail fileDetail, ImportFileBaseService importFileBaseService, List<CsExportExcelHeadDto> dtos)
    {
        this.fileDetail = fileDetail;
        this.appId = fileDetail.getAppId();
        this.sessionId = UUID.randomUUID().toString();;
        this.modeCode = fileDetail.getModeCode();
        this.importFileBaseService = importFileBaseService;
        this.headDtos =dtos;
    }


    /**
     * 这里会一行行的返回头
     *
     * @param headMap headMap
     * @param context context
     */
    @Override
    public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
        Map<String, String> keyMap = new HashMap<>();
        for(int i=headDtos.size()-1;i>=0;i--)
        {
            CsExportExcelHeadDto dto = headDtos.get(i);
            keyMap.put(dto.getTitle().get(0),dto.getKey());
        }

        for(Map.Entry<Integer,String> entry :headMap.entrySet())
        {
            String value = keyMap.get(entry.getValue());
            if(StringUtils.isBlank(value))
            {
                headKeyMap.put(entry.getKey(),entry.getValue());
            }
            else
            {
                headKeyMap.put(entry.getKey(),value);
            }
        }

        log.debug("解析到一条头数据:{}", JSON.toJSONString(headMap));
    }

    @Override
    public void invoke(Map<Integer, String> data, AnalysisContext context) {
        lastDealRow++;
        log.debug("解析到一条数据:{}", JSON.toJSONString(data));
        JSONObject jsonObject = new JSONObject();
        for(Map.Entry<Integer,String> entry :data.entrySet())
        {
            jsonObject.put(headKeyMap.get(entry.getKey()),entry.getValue());
        }
        cachedDataList.add(jsonObject);
        if (cachedDataList.size() >= BATCH_COUNT) {
            saveData();
            cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
        }
    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        saveData();
        log.debug("所有数据解析完成！");
    }

    /**
     * 加上存储数据库
     */
    private void saveData() {
        TransferMessageDto csNioMessage = new TransferMessageDto();
        csNioMessage.setConfig(new TransferMessageConfig());
        csNioMessage.setMessageData(new TransferMessageData());
        csNioMessage.setType(ExportMessageTypeEnum.query_head.code);

        csNioMessage.getConfig().setId(UUID.randomUUID().toString().replace("-",""));
        csNioMessage.getConfig().setAppId(this.appId);
        csNioMessage.getConfig().setModeCode(this.modeCode);
        csNioMessage.getConfig().setSessionId(sessionId);
        csNioMessage.getConfig().setFileType(ExportFileTypeEnum.upload.code);

        csNioMessage.setData(JSON.toJSONBytes(cachedDataList));
        cachedDataList.clear();

        TransferMessageDto resultMessage = SocketManager.sendData(csNioMessage,true);

        if(resultMessage.getConfig().getDealResult() == ExportDealResultTypeEnum.fail.code)
        {
            log.warn("导入保存失败：{}",resultMessage.getConfig().getErrorMessage());
            failMessage = resultMessage.getConfig().getErrorMessage();
            throw new RuntimeException(resultMessage.getConfig().getErrorMessage());
        }

        importFileBaseService.updateStatus(fileDetail.getId(), ImportStatusEnum.deal,lastDealRow,null);
    }
}
